home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / sml_nj / 93src.lha / src / debug / debugger.sml < prev    next >
Encoding:
Text File  |  1993-01-27  |  14.9 KB  |  426 lines

  1. (* Copyright 1989,1992 by AT&T Bell Laboratories *)
  2.  
  3. funsig DEBUGGER(structure Machm : CODEGENERATOR) = sig end
  4.  
  5. functor BogusDebugger(structure Machm : CODEGENERATOR) : sig end = struct end
  6.  
  7. functor RealDebugger(structure Machm : CODEGENERATOR) : sig end =
  8. struct
  9.   open ErrorMsg CompUtil Elaborate Environment System.Timer PrettyPrint
  10.   structure U = System.Unsafe
  11.  
  12.   val update = System.Stats.update
  13.   val say = System.Print.say
  14.  
  15.   (* shared with dbguser/interface.sml *)
  16.   datatype debuglevel = 
  17.        FULL
  18.      | LIVE of ((string * instream) option * (unit -> unit) * (unit -> unit))
  19.      | INTERPOLATION
  20.  
  21.   val _ = DebugUtil.debugStatEnv := #static (!pervasiveEnvRef)
  22.  
  23.   fun instrument (source: Source.inputSource,
  24.               statEnv: StaticEnv.statenv,
  25.               absyn: Absyn.dec) : Absyn.dec =
  26.     let fun dump label absyn =
  27.         if !System.Control.debugging then
  28.           (with_pp (ErrorMsg.defaultConsumer())
  29.              (fn ppstrm =>
  30.                (add_string ppstrm ("\n" ^ label ^ "\n");
  31.             PPAbsyn.ppDec (statEnv,(SOME source)) ppstrm (absyn,1000);
  32.             add_newline ppstrm)))
  33.         else ()
  34.             val _ = dump "BEFORE:" absyn
  35.             val timer = start_timer ()
  36.         val firstPlace = DebugStatic.nextPlace()
  37.         val lastBindTime  = 
  38.            if DebugExec.inCompUnit() then  (* interpolation *)
  39.          DebugExec.currentTime()
  40.            else DebugStatic.lastUnitTime()
  41.         val {absyn,events,evns} =
  42.            DebugInstrum.instrumDec{absyn=absyn,
  43.                        firstPlace=firstPlace,
  44.                        lastBindTime=lastBindTime}
  45.             val time = check_timer timer
  46.         in update(System.Stats.debuginstrum,time);
  47.        infomsg "debug instrument" time;
  48.            dump "AFTER:" absyn;
  49.            DebugStatic.install{inputSource=source,
  50.                    firstPlace=firstPlace,
  51.                    events=events,
  52.                    evns=evns};
  53.        absyn
  54.         end
  55.         
  56.   (* Transformation function guarantees that every function argument
  57.      and every function rule pattern has a "simple" type, i.e., has
  58.      an obvious base type or an explicit type constraint. 
  59.      This notion of simplicity must match that used in DebugBindings. *)
  60.   val constrainer : Absyn.dec -> Absyn.dec =
  61.       let open Absyn Variables TypesUtil
  62.       fun constrainDec dec =
  63.          (case dec of
  64.         VALdec vbl => VALdec(map constrainVb vbl)
  65.           | VALRECdec rvbl => VALRECdec(map constrainRvb rvbl)
  66.           | ABSTYPEdec{abstycs,withtycs,body} =>
  67.             ABSTYPEdec{abstycs=abstycs,withtycs=withtycs,
  68.                    body=constrainDec body}
  69.           | STRdec strbl => STRdec(map constrainStrb strbl)
  70.           | ABSdec strbl => ABSdec(map constrainStrb strbl)
  71.           | FCTdec fctbl => FCTdec(map constrainFctb fctbl)
  72.           | LOCALdec(decin,decout) =>
  73.             LOCALdec(constrainDec decin,constrainDec decout)
  74.           | SEQdec decl => SEQdec(map constrainDec decl)
  75.           | MARKdec(dec,l1,l2) => MARKdec(constrainDec dec,l1,l2)
  76.           | dec => dec)
  77.           and constrainExp exp =
  78.          (case exp of
  79.         RECORDexp lexpl =>
  80.             RECORDexp(map (fn (l,exp) => (l,constrainExp exp)) lexpl)
  81.           | SEQexp expl => SEQexp (map constrainExp expl)
  82.           | APPexp (exp1,exp2) =>
  83.           let fun simple exp =
  84.                (case exp of
  85.               INTexp _ => exp
  86.             | REALexp _ => exp
  87.             | STRINGexp _ => exp
  88.             | CONSTRAINTexp(exp,ty) => 
  89.                   CONSTRAINTexp(constrainExp exp,ty)
  90.             | MARKexp(exp,l1,l2) => MARKexp(simple exp,l1,l2)
  91.             | _ => CONSTRAINTexp(constrainExp exp,mkMETAty()))
  92.           in APPexp(constrainExp exp1,simple exp2)
  93.           end
  94.           | CONSTRAINTexp (exp,ty) => CONSTRAINTexp(constrainExp exp,ty)
  95.           | HANDLEexp(exp1,HANDLER exp2) =>
  96.             HANDLEexp(constrainExp exp1,HANDLER (constrainExp exp2))
  97.           | RAISEexp(exp,t) => RAISEexp(constrainExp exp,t)
  98.           | LETexp(dec,exp) => LETexp(constrainDec dec,constrainExp exp)
  99.           | CASEexp(exp,rl) => CASEexp(constrainExp exp,
  100.                        map constrainRule rl)
  101.           | FNexp(rl,t) => FNexp(map constrainRule rl,t)
  102.           | MARKexp(exp,l1,l2) => MARKexp(constrainExp exp,l1,l2)
  103.           | _ => exp)
  104.       and constrainRule(RULE(pat,exp)) =
  105.               RULE(constrainPat pat,constrainExp exp)
  106.       and constrainPat pat =
  107.            (case pat of 
  108.           WILDpat => pat
  109.         | VARpat(VALvar _) => pat
  110.         | INTpat _ => pat
  111.         | REALpat _ => pat
  112.         | STRINGpat _ => pat
  113.             | CONSTRAINTpat _ => pat
  114.         | _ => CONSTRAINTpat(pat,mkMETAty()))
  115.           and constrainVb (VB{pat,exp,tyvars}) =
  116.             VB{pat=pat,exp=constrainExp exp,tyvars=tyvars}
  117.       and constrainRvb (RVB{var,exp,resultty,tyvars}) =
  118.             RVB{var=var,exp=constrainExp exp,
  119.             resultty=resultty,tyvars=tyvars}
  120.       and constrainStrb (STRB{strvar,def,thin,constraint}) =
  121.             STRB{strvar=strvar,def=constrainStrexp def,thin=thin,
  122.              constraint=constraint}
  123.       and constrainStrexp strexp =
  124.            (case strexp of
  125.           VARstr sv => VARstr sv
  126.         | STRUCTstr{body,str,locations} =>
  127.               STRUCTstr{body=map constrainDec body,str=str,
  128.                 locations=locations}
  129.         | APPstr{oper,argexp,argthin,str} =>
  130.               APPstr{oper=oper,argexp=constrainStrexp argexp,
  131.                  argthin=argthin,str=str}
  132.         | LETstr(dec,strexp) =>
  133.               LETstr(constrainDec dec,constrainStrexp strexp)
  134.         | MARKstr(strexp,l1,l2) =>
  135.               MARKstr(constrainStrexp strexp,l1,l2))
  136.       and constrainFctb (FCTB{fctvar,def}) =
  137.             FCTB{fctvar=fctvar,def=constrainFctexp def}
  138.       and constrainFctexp fctexp =
  139.          (case fctexp of
  140.         VARfct vfct => VARfct vfct
  141.           | LETfct (dec,fct) => 
  142.             LETfct(constrainDec dec, constrainFctexp fct)
  143.           | FCTfct{param,def,thin,constraint} =>
  144.             FCTfct{param=param,def=constrainStrexp def,
  145.                thin=thin,constraint=constraint})
  146.       in constrainDec
  147.       end
  148.  
  149.   (* Filter output of successful parses through instrumenter. *)
  150.   fun parseAndInstrument (source: Source.inputSource) =
  151.       let val parse' = parse constrainer source 
  152.           fun parseit (statEnv:statenv) : parseResult =
  153.           case parse' statEnv 
  154.         of PARSE(absyn,deltaStatEnv) => 
  155.               PARSE(instrument(source,
  156.                       StaticEnv.atop(deltaStatEnv,statEnv),
  157.                       absyn),
  158.                deltaStatEnv)
  159.           | x => x
  160.       in parseit
  161.       end
  162.  
  163.   (* Filter printing of top-level declarations from instrumented code. 
  164.      Debugger declarations begin with an underscore (_). *)
  165.   fun debugPrintDec statenv ppstrm absyn looker =
  166.       let open Absyn Variables
  167.       fun cleanVb (VB{pat,exp,tyvars}) =
  168.             let fun cleanPat(pat as VARpat(VALvar{name=[n],...})) =
  169.               if substring(Symbol.name n,0,1) = "_" then
  170.                 WILDpat
  171.               else pat
  172.               | cleanPat(RECORDpat{pats=ref pl,fields,flex,typ}) =
  173.               RECORDpat{pats=ref (map cleanPat pl),
  174.                     fields=map (fn (l,p) => (l,cleanPat p)) 
  175.                                fields,
  176.                     flex=flex,typ=typ} (* ?? *)
  177.               | cleanPat(APPpat(con,t,pat)) =
  178.               APPpat(con,t,cleanPat pat)
  179.               | cleanPat(CONSTRAINTpat(pat,ty)) =
  180.               CONSTRAINTpat(cleanPat pat,ty)
  181.               | cleanPat(LAYEREDpat(pat1,pat2)) =
  182.               LAYEREDpat(cleanPat pat1, cleanPat pat2)
  183.               | cleanPat pat = pat
  184.         in VB{pat=cleanPat pat,exp=exp,tyvars=tyvars}      
  185.         end
  186.           fun cleanDec (VALdec vbs) = VALdec (map cleanVb vbs)
  187.         | cleanDec (ABSTYPEdec{abstycs,withtycs,body}) =
  188.                ABSTYPEdec{abstycs=abstycs,withtycs=withtycs,body=cleanDec body}
  189.         | cleanDec (LOCALdec(decIn,decOut)) =
  190.                         LOCALdec(decIn, cleanDec decOut)
  191.         | cleanDec (SEQdec decs) = SEQdec(map cleanDec decs)
  192.         | cleanDec (MARKdec(dec,l1,l2)) = MARKdec(cleanDec dec,l1,l2)
  193.         | cleanDec dec = dec
  194.       in PPDec.ppDec statenv ppstrm (cleanDec absyn) looker
  195.      end
  196.  
  197.  
  198.   val debugEnv = DebugEnv.debugEnvironment
  199.  
  200.   val debuggerCommandsEnvRef = ref emptyEnv  (* to speed up lookups *)
  201.   val debugMonitorEnvRef = ref (!debuggerCommandsEnvRef)
  202.  
  203.   fun init FULL f =
  204.       let open DebugMotions DebugStatic DebugUtil
  205.       in case runCompUnit complete f of
  206.            NORMAL r =>  
  207.            (say "[debugging support included]\n";
  208.         r)
  209.      | EXCEPTION e => 
  210.            (rollback(); raise e)
  211.      | ABORT => (* shouldn't happen *)
  212.            (rollback(); raise Abort)
  213.      | INTERRUPT =>
  214.            (rollback(); raise Interrupt)
  215.       end
  216.    | init (LIVE(control,startUp,abortShutDown)) f =
  217.       let open DebugMotions DebugStatic System.Control DebugUtil
  218.       val oldPrimaryPrompt = !primaryPrompt
  219.       and oldSecondaryPrompt = !secondaryPrompt
  220.       fun debugMonitor() = 
  221.           (debugMonitorEnvRef := !debuggerCommandsEnvRef;
  222.            say "[ready to execute under debugger]\n";
  223.            startUp();
  224.            let val baseEnv0 = layerEnv(!topLevelEnvRef,
  225.                        !pervasiveEnvRef)
  226.            val baseEnv = layerEnv(debugEnv,baseEnv0)
  227.            val innerLoopParams = 
  228.                {baseEnv=baseEnv,
  229.             localEnvRef=debugMonitorEnvRef,
  230.             parser=Elaborate.parse (fn dec => dec),
  231.             generate=Machm.generate,
  232.             perform=(fn exec => exec()),
  233.             isolate=(fn f => fn x => f x),
  234.             printer=PPDec.ppDec}
  235.            in primaryPrompt := "[dbg]" ^ oldPrimaryPrompt;
  236.           secondaryPrompt := "[dbg]" ^ oldSecondaryPrompt;
  237.           debugStatEnv := #static baseEnv0;
  238.           case control of
  239.             SOME (fname,stream) => 
  240.                EvalLoop.eval_stream innerLoopParams (fname,stream)
  241.           | NONE => EvalLoop.interact innerLoopParams;
  242.           (* return only via ctrl/d or stream error *)
  243.           abortShutDown();
  244.           abort();
  245.           debugPanic "Returned from abort"
  246.            end)
  247.       fun reset() = 
  248.          (topLevelEnvRef := 
  249.               layerEnv(!debugMonitorEnvRef,!topLevelEnvRef);
  250.           primaryPrompt := oldPrimaryPrompt;
  251.           secondaryPrompt := oldSecondaryPrompt)
  252.       in case runCompUnit debugMonitor f of 
  253.        NORMAL r =>
  254.            (say "[completing normal execution]\n";
  255.         reset();
  256.         r) 
  257.      | EXCEPTION e => 
  258.            (say "[execution terminated by exception]\n";
  259.         rollback();
  260.         reset();
  261.         raise e)
  262.      | ABORT => 
  263.            (say "[execution aborted]\n";
  264.         rollback();
  265.         reset();
  266.         raise Abort)
  267.      | INTERRUPT =>
  268.            (say "[execution interrupted]\n";
  269.         rollback();
  270.         reset();
  271.         raise Interrupt)
  272.      end
  273.     | init INTERPOLATION f =
  274.          (DebugMotions.interpolateCompUnit (fn () => (f(); ()));
  275.       raise Abort)
  276.       
  277.   val debuggerPervasiveEnvRef = ref emptyEnv
  278.  
  279.   fun dbgGenerate x =
  280.       let open System.Control.CG
  281.       val oldInvariant = !invariant
  282.       and oldUnroll = !unroll
  283.       and oldKnownfiddle = !knownfiddle
  284.       in invariant := false;
  285.      unroll := false;
  286.      knownfiddle := false;
  287.      Machm.generate x
  288.      before
  289.      (invariant := oldInvariant;
  290.       unroll := oldUnroll;
  291.       knownfiddle := oldKnownfiddle)
  292.       end
  293.  
  294.   fun dbgParams level =
  295.       {baseEnv= !debuggerPervasiveEnvRef,
  296.        localEnvRef=topLevelEnvRef,
  297.        parser=parseAndInstrument,
  298.        generate=dbgGenerate,
  299.        perform=init level,
  300.        isolate=CompUtil.isolate,
  301.        printer=debugPrintDec} 
  302.  
  303.   fun use_file_dbg (level:debuglevel,fname:string) : unit = 
  304.       (DebugStatic.hideFile fname;
  305.        EvalLoop.eval_stream (dbgParams level)
  306.               (fname,(open_in fname
  307.                 handle Io s =>
  308.                 (say(implode["[use failed: ",s,"]\n"]);
  309.                  raise Error))))
  310.  
  311.  
  312.   fun use_stream_dbg (level:debuglevel,stream:instream) : unit = 
  313.       EvalLoop.eval_stream (dbgParams level) ("<instream>",stream)
  314.       
  315.   fun interpolate_stream(stream:instream) : unit =
  316.       let val dummyEnvRef = ref emptyEnv
  317.           val baseEnv = layerEnv(!debugMonitorEnvRef,
  318.                  layerEnv(debugEnv,
  319.                       layerEnv(!topLevelEnvRef,
  320.                            !debuggerPervasiveEnvRef)))
  321.       in EvalLoop.eval_stream 
  322.          {baseEnv = baseEnv,
  323.           localEnvRef = dummyEnvRef,
  324.           parser = parseAndInstrument,
  325.           generate = dbgGenerate,
  326.           perform = init INTERPOLATION,
  327.           isolate = (fn f => fn x => f x),
  328.           printer = (fn env => fn ppstrm => fn absyn => fn looker => ())}
  329.         ("<interpolation>",stream)
  330.         handle Abort => ()
  331.       end
  332.      
  333.   (* Set up ref which contains values needed by instrumented code at run time.
  334.      This is not very neatly modularized! *)
  335.   val _ = System.Control.Debug.getDebugf := 
  336.        (fn firstEvn =>
  337.         U.cast
  338.         (DebugKernel.times,
  339.          DebugStatic.evnTimesArray firstEvn,
  340.          DebugKernel.break,
  341.          DebugStore.hcreater,
  342.          U.Weak.weak,
  343.          DebugStore.updatedRList,
  344.          DebugStore.PCONS,
  345.          DebugStore.updatedAList,
  346.          Array.array))
  347.  
  348.   (* Set up values for user-space interface.  
  349.      It is very important that types match those on user-space end,
  350.      since the interface is not type-checked. *)
  351.   val _ =
  352.     let val old_interface = !System.Control.Debug.interface
  353.     in System.Control.Debug.interface := 
  354.       (fn 
  355.          0 => U.cast debuggerPervasiveEnvRef
  356.        | 1 => U.cast use_file_dbg
  357.        | 2 => U.cast use_stream_dbg
  358.        | 3 => U.cast DebugMotions.withEstablishedTime
  359.        | 4 => U.cast DebugExec.currentTime
  360.        | 5 => U.cast (fn() => DebugStatic.immediatePlaces(
  361.                   DebugStatic.placesFor(DebugExec.currentEvn())))
  362.        | 6 => U.cast (fn () => (!DebugExec.initialTime,!DebugExec.finalTime))
  363.        | 7 => U.cast DebugQueries.lastTimes
  364.        | 8 => U.cast DebugMotions.jump
  365.        | 9 => U.cast DebugMotions.binSearch
  366.        | 10 => U.cast DebugQueries.callTrace
  367.        | 11 => U.cast DebugQueries.getVal
  368.        | 12 => U.cast DebugQueries.printVal
  369.        | 13 => U.cast DebugUtil.isFn
  370.        | 14 => U.cast DebugQueries.printBind 
  371.        | 15 => U.cast DebugUtil.debugdebug
  372.        | 16 => U.cast (DebugStore.updatedAList,
  373.                DebugStore.updatedRList,
  374.                DebugStore.createdList,
  375.                DebugStore.hcreatea,
  376.                DebugStore.hcreater)
  377.        | 17 => U.cast DebugStatic.eventPlacesAfter
  378.        | 18 => U.cast DebugStatic.eventPlacesBefore
  379.        | 19 => U.cast (DebugMotions.setHandler, (* special exn handling! *)
  380.                DebugSignals.inqHandler,
  381.                DebugSignals.maskSignals,
  382.                DebugSignals.pause)
  383.        | 20 => U.cast DebugMotions.complete
  384.        | 21 => U.cast DebugMotions.abort
  385.        | 22 => U.cast DebugExec.inCompUnit
  386.        | 23 => U.cast (fn () => !DebugExec.blockingExn)
  387.        | 24 => U.cast DebugIO.logit
  388.        | 25 => U.cast DebugQueries.eventDesc
  389.        | 26 => U.cast DebugRun.maxTimeDelta
  390.        | 27 => U.cast DebugKernel.times
  391.        | 28 => U.cast DebugQueries.caller
  392.        | 29 => U.cast DebugUtil.infinity
  393.        | 30 => U.cast DebugEnv.setEnvTime
  394.        | 31 => U.cast DebugQueries.atCall
  395.        | 32 => U.cast DebugEnv.useSpecial
  396.        | 33 => U.cast DebugStatic.charnoForLinepos
  397.        | 34 => U.cast DebugUtil.sizereport
  398.        | 35 => U.cast DebugInstrum.instrumLevel
  399.        | 36 => U.cast DebugRun.memoLevel
  400.        | 37 => U.cast DebugRun.dumpCache
  401.        | 38 => U.cast DebugRun.dfactor
  402.        | 39 => U.cast (fn () => DebugKernel.execTime)
  403.        | 40 => U.cast DebugRun.maxStates
  404.        | 41 => U.cast DebugRun.preCachingEnabled
  405.        | 42 => U.cast DebugMotions.cpCost
  406.        | 43 => U.cast DebugRun.pcfactor
  407.        | 44 => U.cast DebugRun.zapFactor
  408.        | 45 => U.cast DebugRun.strictLru
  409.        | 46 => U.cast DebugRun.cacheRatio
  410.        | 47 => U.cast DebugRun.zapCount
  411.        | 48 => U.cast interpolate_stream
  412.        | 49 => U.cast debuggerCommandsEnvRef
  413.        | 50 => U.cast DebugMotions.setSignal
  414.        | 51 => U.cast DebugMotions.clearSignal
  415.        | 52 => U.cast (fn () => 
  416.                case DebugSignals.deliverableSignal() of
  417.              SOME(signal,_) => SOME signal
  418.                | NONE => NONE)
  419.        | 53 => U.cast DebugSignals.setHalting
  420.        | 54 => U.cast DebugQueries.exnArg
  421.        | 55 => U.cast DebugStatic.lineposForCharno
  422.        | q => old_interface q)
  423.     end (* let ... *)
  424. end
  425.  
  426.